package com.ftg.learn.datahandle.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ftg.learn.datahandle.service.SubjectScoreService;
import com.ftg.learn.excelEntity.SubjectScoreExcelEntitiy;
import com.ftg.learn.util.R;
import com.ftg.learn.util.RMessCommEnum;
import jakarta.annotation.Resource;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author 布衣
 */
@Service
public class SubjectScoreServiceImpl implements SubjectScoreService {

    //线程池
    ExecutorService es = Executors.newFixedThreadPool(5);
    ExecutorService wash = Executors.newSingleThreadExecutor();
    //切片数量
    private static final int BATCH_COUNT = 20;
    private static final int WASH_COUNT = 10;

    private List<SubjectScoreExcelEntitiy> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private List<SubjectScoreExcelEntitiy> washDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    @Resource
    RabbitTemplate rabbitTemplate;

    @Resource
    ObjectMapper objectMapper;

    @Override
    public R<String> readExcelWithSubjectScore(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), SubjectScoreExcelEntitiy.class, new ReadListener<SubjectScoreExcelEntitiy>() {
                @Override
                public void invoke(SubjectScoreExcelEntitiy o, AnalysisContext analysisContext) {
                    //容错
                    System.out.println(!StringUtils.isEmpty(o.getStuNo())+"=="+o.getName());
                    if (!StringUtils.isEmpty(o.getStuNo())) {
                        cachedDataList.add(o);
                        if (cachedDataList.size() >= BATCH_COUNT) {
                            List<SubjectScoreExcelEntitiy> list = new ArrayList<>(cachedDataList);
                            //调用线程来完处理
                            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                            es.execute(() -> {
                                try {
                                    processDataHandle(list);
                                } catch (JsonProcessingException e) {
                                    throw new RuntimeException(e);
                                }
                            });
                        }
                    } else {
                        washDataList.add(o);
                        if (washDataList.size() > WASH_COUNT) {
                            wash.execute(() -> {
                                try {
                                    processWashDataHandle(washDataList);
                                } catch (JsonProcessingException e) {
                                    throw new RuntimeException(e);
                                }
                            });
                        }
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                    if (!cachedDataList.isEmpty()) {
                        es.execute(() -> {
                            try {
                                processDataHandle(cachedDataList);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException(e);
                            }
                        });
                    }
                    if (!washDataList.isEmpty()) {
                        wash.execute(() -> {
                            try {
                                processWashDataHandle(washDataList);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException(e);
                            }
                        });
                    }
                }
            }).headRowNumber(1).sheet(0).doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return R.build(RMessCommEnum.RABBITMQ_MESS_SEND_SUCCESS);
    }

    private void processWashDataHandle(List<SubjectScoreExcelEntitiy> washDataList) throws JsonProcessingException {
        rabbitTemplate.convertAndSend("", "subjectScoreQueueWash", objectMapper.writeValueAsString(washDataList));
    }

    private void processDataHandle(List<SubjectScoreExcelEntitiy> cachedDataList) throws JsonProcessingException {
        rabbitTemplate.convertAndSend("", "subjectScoreQueue", objectMapper.writeValueAsString(cachedDataList));
    }


}
